"""
Copyright 2012 Wieser Dietmar, Margit Mutschlechner.

This file is part of Multimedia Social Networking Platform.

Multimedia Social Networking Platform is free software: 
you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Multimedia Social Networking Platform is distributed
in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Multimedia Social Networking Platform.  
If not, see <http://www.gnu.org/licenses/>.

"""

import time
from msnp.service.network.model import CustodyModel
from msnp.service.utils import StringCompare

class ReturnType:
    """Class containing the 16 return types for remote calls. This is one of "ERROR", "SUCCESSFUL", "LOGIN_WRONG_USERNAME",
    "LOGIN_WRONG_PASSWORD", "REGISTER_NAME_NOT_AVAILABLE", "AUTHENTICATION_NO_PASSWORD", "UPDATE_SUCCESSOR_ERROR",
    "UPDATE_PREDECESSOR_ERROR","LOW_LEVEL_PEER_NOT_IN_LIST", "RECONNECT", "FORCE_REHELLO", "GROUP_ALREADY_EXISTS",
    "PEER_OFFLINE", "ALREADY_LOGGED_IN", "NO_KNOWN_PEER_ONLINE", "NO_PLAYER_SELECTED"."""
    ERROR = -1
    SUCCESSFUL = 0
    LOGIN_WRONG_USERNAME = 1
    LOGIN_WRONG_PASSWORD = 2
    REGISTER_NAME_NOT_AVAILABLE = 3
    AUTHENTICATION_NO_PASSWORD = 4
    UPDATE_SUCCESSOR_ERROR = 5
    UPDATE_PREDECESSOR_ERROR = 6
    LOW_LEVEL_PEER_NOT_IN_LIST = 7
    RECONNECT = 8
    FORCE_REHELLO = 9
    GROUP_ALREADY_EXISTS = 10
    PEER_OFFLINE = 11
    ALREADY_LOGGED_IN = 12
    NO_KNOWN_PEER_ONLINE = 13
    NO_PLAYER_SELECTED = 14
        
    @classmethod
    def returnTypeToString(cls, type):
        """Class method to return a detailed message describing the return type.
        
        Returns:
            A String containing the detailed return message.
        """
        s = 'type ' + str(type) + ' - '
        if type == cls.ERROR:
            return s + 'General Error (not expected)'
        elif type == cls.SUCCESSFUL:
            return s + 'Successful'
        elif type == cls.LOGIN_WRONG_USERNAME:
            return s + 'Wrong username'
        elif type == cls.LOGIN_WRONG_PASSWORD:
            return s + 'Wrong password'
        elif type == cls.REGISTER_NAME_NOT_AVAILABLE:
            return s + 'Name already in use by another user'
        elif type == cls.AUTHENTICATION_NO_PASSWORD:
            return s + 'No password entered'
        elif type == cls.UPDATE_SUCCESSOR_ERROR:
            return s + 'Error during updating successor'
        elif type == cls.UPDATE_PREDECESSOR_ERROR:
            return s + 'Error during updating predecessor'
        elif type == cls.LOW_LEVEL_PEER_NOT_IN_LIST:
            return s + 'Low level peer is not in the list of online LLPs'
        elif type == cls.RECONNECT:
            return s + 'Force reconnect'
        elif type == cls.FORCE_REHELLO:
            return s + 'Force rehello'
        elif type == cls.GROUP_ALREADY_EXISTS:
            return s + 'Group already exists'
        elif type == cls.ALREADY_LOGGED_IN:
            return s + 'Already logged in'
        elif type == cls.NO_KNOWN_PEER_ONLINE:
            return s + 'No known peer is online'
        elif type == cls.NO_PLAYER_SELECTED:
            return s + 'No player selected'
        else:
            return s + 'Unknown return type'

class MemberStatusChangedReturnType():
    """Class containing the seven return types for member status changes. This is one of "ERROR", "SUCCESSFUL", "ALREADY_MEMBER",
    "IS_NOT_MEMBER", "GROUP_NOT_EXISTING", "STATUSCHANGE_NOT_ALLOWED" or "GROUP_IS_INACTIVE"."""
    ERROR = "ERROR"
    SUCCESSFUL = "SUCCESSFUL"
    ALREADY_MEMBER = "ALREADY_MEMBER"
    IS_NOT_MEMBER = "IS_NOT_MEMBER"
    GROUP_NOT_EXISTING = "GROUP_NOT_EXISTING"
    STATUSCHANGE_NOT_ALLOWED = "STATUSCHANGE_NOT_ALLOWED"
    GROUP_IS_INACTIVE = 'GROUP_IS_INACTIVE'
    
    @classmethod
    def toString(cls, type):
        """Class method to return a detailed message describing the return type.
        
        Returns:
            A String containing the detailed return message.
        """
        if type == cls.ERROR:
            return "unknown error"
        elif type == cls.SUCCESSFUL:
            return "successful"
        elif type == cls.ALREADY_MEMBER:
            return "the user is already a member of the group"
        elif type == cls.IS_NOT_MEMBER:
            return "the user is not a member of the group"
        elif type == cls.GROUP_NOT_EXISTING:
            return "the group does not exist"
        elif type == cls.STATUSCHANGE_NOT_ALLOWED:
            return "the executed change of membership status is not allowed"
        elif type == cls.GROUP_IS_INACTIVE:
            return "the group is not active"
        else:
            return "unknown"
        
class BackupType():
    """Class containing the three backup types. This is one of "UPDATE", "DELETE_SELECTED_BACKUPFROM" or "DELETE_ALL"."""
    DELETE_ALL = 'delete_all'
    DELETE_SELECTED_BACKUPFROM = 'delete_selected_backupfrom'
    UPDATE = 'update'

class MemberStatus():
    """Class containing the four membership statuses. This is one of "ACTIVE", "NOT_CONFIRMED", "DELETED" or "BLOCKED"."""
    ACTIVE = 'ACTIVE'
    NOT_CONFIRMED = 'NOT_CONFIRMED'
    DELETED = 'DELETED'
    BLOCKED = 'BLOCKED'
    
class ChatMessageStatus():
    """Class containing the five chat message statuses. This is one of "RECEIVED", "SENDING", "SENT", "PEER_OFFLINE" or "PEER_NOT_EXISTENT"."""
    RECEIVED = "received"
    SENDING = "sending"
    SENT = "sent"
    PEER_OFFLINE = "peer_offline"
    PEER_NOT_EXISTENT = "peer_not_existent"


class BackupContent():
    """This class contains backup contents, each instance represents the backup of one user stored in the ptp database.
    
    Parameters:
        __fromUsername: A String containing the name of the user that is responsible for this backup.
        __users: A list of User objects containing the users belonging to this backup.
        __userGroups: A list of UserGroup objects containing the user-group relations belonging to this backup.
        __groups: A list of Group objects containing the groups belonging to this backup.
        __type: A BackupType object, either UPDATE, DELETE_SELECTED_BACKUPFROM or DELETE_ALL.
        __timestamp: A float value containing the exact timestamp of the backup.
    """
    def __init__(self, fromUsername, users, userGroups, groups, type):
        """The init method."""
        if fromUsername != None:
            fromUsername = unicode(fromUsername)
        self.__fromUsername = fromUsername
        self.__users = users
        self.__userGroups = userGroups
        self.__groups = groups
        self.__type = type
        self.__timestamp = None
        
    def setFromUsername(self, fromUsername):
        """Set the parameter __fromUsername."""
        if fromUsername != None:
            fromUsername = unicode(fromUsername)
        self.__fromUsername = fromUsername
        
    def getFromUsername(self):
        """Returns the parameter __fromUsername."""
        return self.__fromUsername
    
    def getUsers(self):
        """Returns the parameter __users."""
        return self.__users
    
    def containsUser(self, user):
        """Checks whether the given user is contained in the backuped users or not
        
        Args:
            user: The User object to search for in the backuped users.
            
        Returns:
            True is returned if the given user is contained in the backuped users, False otherwise.
        """
        if self.__users != None:
            for u in self.__users:
                if u.getUsername() == user.getUsername():
                    if u.getDisplayname() == user.getDisplayname():
                        if u.getPassword() == user.getPassword():
                            uMsgs = u.getMessages()
                            userMsgs = user.getMessages()
                            if uMsgs == None and userMsgs == None:
                                return True
                            if uMsgs != None and userMsgs != None and len(uMsgs) == len(userMsgs):
                                for uMsg in uMsgs:
                                    msgFound = False
                                    for userMsg in userMsgs:
                                        if CustodyModel.isEqual(uMsg, userMsg):
                                            msgFound = True
                                            break
                                    if msgFound == False:
                                        return False
                                return True
        return False
    
    #TODO combine the containsUser and containsUsername method
    def containsUsername(self, username):
        """Checks whether the given username is contained in the backuped users or not
        
        Args:
            user: A String containing the user name to search for in the backuped users.
            
        Returns:
            True is returned if the given username is contained in the backuped users, False otherwise.
        """
        if self.__users != None:
            for u in self.__users:
                if u.getUsername() == username:
                    return True
        return False
    
    def getUserGroups(self):
        """Returns the parameter __userGroups."""
        return self.__userGroups
    
    def containsUserGroup(self, userGroup):
        """Checks whether the given user-group relation is contained in the backuped user-group relations or not
        
        Args:
            user: The UserGroup object to search for in the backuped users-group relations.
            
        Returns:
            True is returned if the given user-group relation is contained in the backuped user-group relations, False otherwise.
        """
        if self.__userGroups != None:
            for ug in self.__userGroups:
                if ug.getUsername() == userGroup.getUsername():
                    if ug.getGroupname() == userGroup.getGroupname():
                        if ug.getOwnername() == userGroup.getOwnername():
                            return True
        return False
    
    def getGroups(self):
        """Returns the parameter __groups."""
        return self.__groups
    
    def containsGroup(self, group):
        """Checks whether the given roup is contained in the backuped groups or not
        
        Args:
            user: The Group object to search for in the backuped groups.
            
        Returns:
            True is returned if the given group is contained in the backuped groups, False otherwise.
        """
        if self.__groups != None:
            for g in self.__groups:
                if g.getGroupname() == group.getGroupname():
                    if g.getOwnername() == group.getOwnername():
                        if g.hasDetails() == False or group.hasDetails() == False:
                            return True
                        if g.getDisplayname() == group.getDisplayname():
                            if g.getDescription() == group.getDescription():
                                if g.isActive() == group.isActive():
                                    gGenres = g.getGenres()
                                    groupGenres = group.getGenres()
                                    if gGenres == None and groupGenres != None and len(groupGenres) > 0:
                                        return False
                                    if gGenres != None and len(gGenres) > 0 and groupGenres == None:
                                        return False
                                    if (gGenres == None or len(gGenres) == 0)and (groupGenres == None or len(groupGenres) == 0):
                                        return True
                                    if len(gGenres) == len(groupGenres):
                                        for gGenre in gGenres:
                                            if groupGenres.__contains__(gGenre) == False:
                                                return False
                                        gMembers = g.getMembers()
                                        groupMembers = group.getMembers()
                                        if gMembers == None and groupMembers != None and len(groupMembers) > 0:
                                            return False
                                        if gMembers != None and len(gMembers) > 0 and groupMembers == None:
                                            return False
                                        if len(gMembers) == len(groupMembers):
                                            for (gMember, status) in gMembers.iteritems():
                                                if groupMembers.__contains__(gMember) == False:
                                                    return False
                                                if groupMembers.get(gMember) != status:
                                                    return False
                                            return True
        return False
    
    def containsMemberGroup(self, membername, groupname):
        """Checks whether the given member-group relation is contained in the backuped member-group relations or not
        
        Args:
            user: The MemberGroup object to search for in the backuped member-group relations.
            
        Returns:
            True is returned if the given member-group relation is contained in the backuped member-group relations, False otherwise.
        """
        if self.__groups != None:
            for g in self.__groups:
                if g.getGroupname() == groupname:
                    if g.containsMember(membername):
                        return True
        return False
    
    def setType(self, type):
        """Sets the parameter __type to the given value."""
        self.__type = type
    
    def getType(self):
        """Returns the parameter __type."""
        return self.__type
    
    def setTimestamp(self, timestamp):
        """Sets the parameter __timestamp to the given value."""
        self.__timestamp = timestamp
        
    def getTimestamp(self):
        """Returns the parameter __timestamp."""
        return self.__timestamp
    
    def getGroupnamesForMembername(self, membername):
        """Returns all groups stored in the backup where the given user is a member of.
        
        Args:
            membername: A String containing the name of the user which groups should be returned.
            
        Returns:
            A list of Group objects is returned or None if there are no such groups.
        """
        if self.__groups != None:
            groupnames = []
            for g in self.__groups:
                if g != None:
                    if g.containsMember(membername):
                        groupnames.append(g.getGroupname())
            return groupnames
        return None
    
    def getActiveGroupnamesForMembername(self, membername):
        """Returns all groups stored in the backup where the given user is an active member of.
        
        Args:
            membername: A String containing the name of the user which active groups should be returned.
            
        Returns:
            A list of Group objects is returned or None if there are no such groups.
        """
        if self.__groups != None:
            groupnames = []
            for g in self.__groups:
                if g != None:
                    if g.containsActiveMember(membername):
                        groupnames.append(g.getGroupname())
            return groupnames
        return None
    
    def getUserGroupsForUsers(self, users):
        """Returns all user-group relations stored in the backup where the given users are contained.
        
        Args:
            user: A list of User objects for which the user-group relations should be returned.
            
        Returns:
            A list of UserGroup objects is returned or None if there are no such user-group relations.
        """
        userGroups = []
        if users != None and self.__userGroups != None:
            for user in users:
                username = user.getUsername()
                for ug in self.__userGroups:
                    if username == ug.getUsername():
                        userGroups.append(ug)
        if len(userGroups) == 0:
            userGroups = None
        return userGroups
    
    
    def getGroupsForUserGroups(self, userGroups):
        """Returns all groups stored in the backup that are contained in the given user-group relations.
        
        Args:
            userGroups: A list of UserGroup objects for which the contained groups should be returned.
            
        Returns:
            A list of Group objects is returned or an empty list if there are no such groups.
        """
        groups = []
        if userGroups != None and self.__groups != None:
            for group in self.__groups:
                groupname = group.getGroupname()
                ownername = group.getOwnername()
                for ug in userGroups:
                    if groupname == ug.getGroupname() and ownername == ug.getOwnername():
                        groups.append(group)
                        break
        if len(groups) == 0:
            groups = None
        return groups
    
    def toString(self):
        """Returns the BackupContent object in a readable form as a String."""
        retString = ""
        if self.__users != None:
            for user in self.__users:
                retString += user.toString() + "\n"
        if self.__groups != None:
            for group in self.__groups:
                retString += group.toString() + "\n"
        if self.__userGroups != None:
            for usergroup in self.__userGroups:
                retString += usergroup.toString() + "\n"
        return retString


class User():
    """This class contains users, each instance represents one entry of the user table in the ptp database.
    
    Parameters:
        __username: A String containing the name of the user.
        __displayname: A String containing the display name of the user.
        __password: A String containing the passwordof the user.
        __backupFromUsername: A String containing the name of the user that is responsible for this user or None if the current user is responsible. Default None.
        __timestamp: A float value containing the exact timestamp of the backup.
        __messages: A list of Message objects belonging to this user. Default None.
    """
    def __init__(self, username, displayname, password, timestamp, backupFromUsername=None, messages=None):
        """The init method."""
        if username != None:
            username = unicode(username)
        if displayname != None:
            displayname = unicode(displayname)
        if password != None:
            password = unicode(password)
        if backupFromUsername != None:
            backupFromUsername = unicode(backupFromUsername)
        self.__username = username
        if displayname == None or len(displayname) <= 0:
            self.__displayname = username
        else:
            self.__displayname = displayname
        self.__password = password
        self.__backupFromUsername = backupFromUsername
        self.__timestamp = timestamp
        self.__messages = messages
    
    def setBackupFromUsername(self, name):
        """Sets the parameter __backupFromUsername to the given value."""
        if name != None:
            name = unicode(name)
        self.__backupFromUsername = name   
    
    def getUsername(self):
        """Returns the parameter __username."""
        return self.__username
    
    def getDisplayname(self):
        """Returns the parameter __displayname."""
        return self.__displayname
    
    def getPassword(self):
        """Returns the parameter __password."""
        return self.__password
    
    def getBackupFromUsername(self):
        """Returns the parameter __backupFromUsername."""
        return self.__backupFromUsername
    
    def getTimestamp(self):
        """Returns the parameter __timestamp."""
        return self.__timestamp
    
    def setTimestamp(self, timestamp):
        """Sets the parameter __timestamp."""
        self.__timestamp = timestamp
        
    def getMessages(self):
        """Returns the parameter __messages."""
        return self.__messages
    
    def setMessages(self, messages):
        """Sets the parameter __messages."""
        self.__messages = messages
    
    def toString(self):
        """Returns the User object in a readable form as a String."""
        userString = "USER: "
        userString += (self.__username) if (self.__username != None) else "None"
        userString += (" (" + self.__displayname + "), ") if (self.__displayname != None) else "(None), "
        userString += (" pw = " + self.__password + ", ") if (self.__password != None) else " pw = None, "
        userString += (" backup from = " + self.__backupFromUsername) if (self.__backupFromUsername != None) else " backup from = None, "
        userString += " timestamp: " + str(self.__timestamp) + ", "
        if self.__messages == None:
            userString += "no messages"
        else:
            userString += str(len(self.__messages)) + " messages:"
            for msg in self.__messages:
                userString += " - " + msg.getQueueType()
        return userString
    
class Group():
    """This class contains users, each instance represents one entry of the user table in the ptp database.
    
    Parameters:
        __groupname: A String containing the name of the group.
        __ownername: A String containing the name of the group's owner.
        __displayname: A String containing the display name of the group. Default None.
        __description: A String containing the description of the group. Default None.
        __genres: A list of Genre objects containing the genres belonging to this group. Default None.
        __isActive: A boolean value, True if the group is active, False otherwise. Default True.
        __members: A list of Member objects belonging to this group. Default None.
    """
    def __init__(self, groupname, ownername, displayname=None, description=None, genres=None, isActive=True, members=None):
        """The init method."""
        if groupname != None:
            groupname = unicode(groupname)
        if displayname != None:
            displayname = unicode(displayname)
        if ownername != None:
            ownername = unicode(ownername)
        if description != None:
            description = unicode(description)
        self.__groupname = groupname
        self.__displayname = displayname
        self.__ownername = ownername
        self.__description = description
        self.__genres = genres
        self.__isActive = isActive
        self.__members = members
    
    def getGroupname(self):
        """Returns the parameter __groupname."""
        return self.__groupname
    
    def getDisplayname(self):
        """Returns the parameter __displayname."""
        return self.__displayname
    
    def getOwnername(self):
        """Returns the parameter __ownername."""
        return self.__ownername
    
    def getDescription(self):
        """Returns the parameter __description."""
        return self.__description
    
    def getGenres(self):
        """Returns the parameter __genre."""
        return self.__genres
    
    def addGenre(self, genre):
        """Adds the given genre to the list of group genres."""
        if self.__genres == None:
            self.__genres = []
        if self.containsGenre(genre.getName()):
            return
        self.__genres.append(genre)
        
    def containsGenre(self, genreName):
        """Checks whether the given genre is contained in the list of group genres.
        
        Args:
            genreName: A String containing the name of the genre to search for.
        
        Returns:
            True is returned if the given genre is contained in the list of group genres, False otherwise.
        """
        if self.__genres != None:
            for genre in self.__genres:
                if StringCompare.isEquals(genre.getName(), genreName):
                    return True
        return False
    
    def isActive(self):
        """Returns the parameter __isActive."""
        return self.__isActive
    
    def getMembers(self):
        """Returns the parameter __members."""
        return self.__members
    
    def getMembersByStatus(self, status):
        """Retrieves all members that have a certain given status.
        
        Args:
            status: A MemberStatus object containing the state of the member, either ACTIVE, NOT_CONFIRMED, BLOCKED or DELETED.
        
        Returns:
            A list of Member objects with the given status is returned, or an empty list if there is no such members.
        """
        retMembers = []
        if self.__members != None:
            for member in self.__members:
                if member.getStatus() == status:
                    retMembers.append(member)
        return retMembers
    
    def getMember(self, membername):
        """Returns a specific member.
        
        Args:
            membername: A String containing the name of the searched member.
        
        Returns:
            A Member object corresponding to the given membername is returned.
        """
        if self.__members != None:
            for member in self.__members:
                if member.getName() == membername:
                    return member
        return None
    
    def setMembers(self, members):
        """Sets the parameter __members to the given one."""
        self.__members = members
    
    def containsMember(self, membername):
        """Checks whether the given membername is contained in the members."""
        if self.__members != None:
            for member in self.__members:
                if member.getName() == membername:
                    return True
        return False
    
    def addMember(self, membername, status, timestamp):
        """Creates a Member object out of the given parameters and adds it to the list of members.
        
        Args:
            membername: A String containing the name of the new member.
            status: A String containing the status of the new member, one of ACTIVE, NOT_CONFIRMED, BLOCKED or DELETED.
        
        Returns:
            True is returned if the member did not exist yet, otherwise False.
        """
        if self.containsMember(membername):
            return False
        if self.__members == None:
            self.__members = []
        self.__members.append(Member(membername, status, timestamp))
        return True
    
    def setMemberStatus(self, membername, status):
        """Sets the status of the member that corresponds to the given member name to the given status."""
        if self.__members != None:
            for member in self.__members:
                if member.getName() == membername:
                    member.setStatus(status)
                    return True
        return False
        
    def setStatus(self, isActive):
        """Sets the parameter __isActive to the given one."""
        self.__isActive = isActive
        
    def hasDetails(self):
        """Checks whether the group contains details, i.e. if at least one of the parameters __description, __displayname, __genere or __members is set."""
        if (self.__description != None and len(self.__description) > 0) or (self.__displayname != None and len(self.__displayname) > 0) or (self.__genres != None and len(self.__genres) > 0) or (self.__members != None and len(self.__members) > 0):
            return True
        
    def compareValues(self, groupname, displayname, genre):
        """Checks whether the group corresponds to the given parameters."""
        print "group " + self.getGroupname() + ":"
        groupnameOk = True
        if groupname != None and len(groupname) > 0:
            if groupname != self.getGroupname():
                print "groupname=False"
                groupnameOk = False
        displayOk = True
        if displayname != None and len(displayname) > 0:
            if displayname != self.getDisplayname():
                print "displayname=False"
                displayOk = False
        genreOk = True
        if genre != None:
            if self.containsGenre(genre.getName()) == False:
                print "displayname=False"
                genreOk = False
        if displayOk and genreOk and groupnameOk:
            return True
        return False

    def toString(self):
        """Returns the Group object in a readable form as a String."""
        groupString = "GROUP: "
        groupString += (self.__groupname) if (self.__groupname != None) else "None"
        groupString += (", owner = " + self.__ownername) if (self.__ownername != None) else " owner = None"
        if self.__displayname == None and self.__genre == None and self.__description == None and self.__members == None:
            groupString += " --> don't know details about group"
        else:
            groupString += (" !!NOT ACTIVE!! ") if (self.__isActive == False) else "," 
            groupString += (" displayname = " + self.__displayname + ", ") if (self.__displayname != None) else " displayname = None,"
            groupString += (" description = " + self.__description + ", ") if (self.__description != None) else " description = None,"
            if self.__genres != None:
                groupString += " genres = "
                for genre in self.__genres:
                    groupString += genre.getName() + ","
            else:
                groupString += " no genres,"
            groupString += " members: "
            if self.__members != None:
                for member in self.__members:
                    groupString += member.getName() + " (" + member.getStatus() + "), "
            else:
                groupString += "no members"

        return groupString
    
    
class UserGroup():
    """This class contains user-group relations, each instance represents one entry of the user-group table in the ptp database.
    
    Parameters:
        __username: A String containing the name of the user.
        __groupname: A String containing the name of the group.
        __ownername: A String containing the name of the owner.
    """
    def __init__(self, username, groupname, ownername):
        """The init method."""
        if username != None:
            username = unicode(username)
        if groupname != None:
            groupname = unicode(groupname)
        if ownername != None:
            ownername = unicode(ownername)
        self.__username = username
        self.__groupname = groupname
        self.__ownername = ownername
    
    def getUsername(self):
        """Returns the parameter __username."""
        return self.__username
    
    def getGroupname(self):
        """Returns the parameter __groupname."""
        return self.__groupname
    
    def getOwnername(self):
        """Returns the parameter __ownername."""
        return self.__ownername
    
    def toString(self):
        """Returns the UserGroup object in a readable form as a String."""
        usergroupString = "USER-GROUP: "
        usergroupString += (self.__username + " - ") if (self.__username != None) else "None - "
        usergroupString += (self.__groupname) if (self.__groupname != None) else "None"
        usergroupString += (" (owner is '" + self.__ownername + "')") if (self.__ownername != None) else " (owner is None)"
        return usergroupString

class Genre():
    """This class contains genres, each instance represents one entry of the genre table in the ptp database.
    
    Parameters:
        __name: A String containing the name of the genre.
    """
    def __init__(self, name):
        """The init method."""
        if name != None:
            name = unicode(name)
        self.__name = name
    
    def getName(self):
        """Returns the parameter __name."""
        return self.__name
    
class Member():
    """This class contains members. This is a part of the member-group table in the ptp database.
    
    Parameters:
        __name: A String containing the name of the member.
        __status: A String containing the status of the member.
        __timestamp: A float value containing the timestamp of the last status change.
    """
    def __init__(self, name, status, timestamp):
        """The init method."""
        if name != None:
            name = unicode(name)
        self.__name = name
        self.__status = status
        self.__timestamp = timestamp
    
    def getName(self):
        """Returns the parameter __name."""
        return self.__name
    
    def getStatus(self):
        """Returns the parameter __status."""
        return self.__status
    
    def getTimestamp(self):
        """Returns the parameter __timestamp."""
        return self.__timestamp
    
    def setStatus(self, status):
        """Sets the parameter __status to the given one."""
        self.__status = status
    
    
        
class ChatMessage():
    """This class contains chat messages, each instance represents one entry of the message table in the ptp database.
    
    Parameters:
        __senderName: A String containing the name of the sender.
        __message: A String containing the message itself.
        __timestamp: A float value containing the timestamp when the message was sent.
        __status: A String containing the status of the message, one of "RECEIVED", "SENDING", "SENT", "PEER_OFFLINE" or "PEER_NOT_EXISTENT". Default "RECEIVED".
    """
    def __init__(self, senderName, message, timestamp, status=ChatMessageStatus.RECEIVED):
        """The init method."""
        if senderName != None:
            senderName = unicode(senderName)
        if message != None:
            message = unicode(message)
        self.__senderName = senderName
        self.__message = message
        self.__timestamp = timestamp
        self.__status = status
        
    def getSendername(self):
        """Returns the parameter __senderName."""
        return self.__senderName
    
    def getMessage(self):
        """Returns the parameter __message."""
        return self.__message
    
    def getTimestamp(self):
        """Returns the parameter __timestamp."""
        return self.__timestamp
    
    def getLocaltime(self):
        """Returns the parameter __timestamp formatted as localtime."""
        return time.localtime(self.__timestamp)
    
    def getStatus(self):
        """Returns the parameter __status."""
        return self.__status
    
    def setStatus(self, status):
        """Sets the parameter __status."""
        self.__status = status
    
    @classmethod
    def sortChatMessages(cls, messages):
        """Class method to sort the given messages ascending according to the timestamp."""
        return sorted(messages, key=lambda message: message.getTimestamp())
    
    
    
